{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Mutable Sequences"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When dealing with mutable sequences, we have a few more things we can do - essentially adding, removing and replacing elements in the sequence.\n",
    "\n",
    "This **mutates** the sequence. The sequence's memory address has not changed, but the internal **state** of the sequence has."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Replacing Elements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can replace a single element as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932141064\n",
      "1979932141064 ['a', 2, 3, 4, 5]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4, 5]\n",
    "print(id(l))\n",
    "l[0] = 'a'\n",
    "print(id(l), l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can remove all elements from the sequence:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4, 5]\n",
    "l.clear()\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that this is **NOT** the same as doing this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4, 5]\n",
    "l = []\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The net effect may look the same, `l` is an empty list, but observe the memory addresses:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932698824\n",
      "[] 1979932698824\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4, 5]\n",
    "print(id(l))\n",
    "l.clear()\n",
    "print(l, id(l))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "vs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932699144\n",
      "[] 1979932698824\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4, 5]\n",
    "print(id(l))\n",
    "l = []\n",
    "print(l, id(l))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the second case you can see that the object referenced by `l` has changed, but not in the first case."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Why might this be important?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Suppose you have the following setup:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[] ['Spades', 'Hearts', 'Diamonds', 'Clubs']\n"
     ]
    }
   ],
   "source": [
    "suits = ['Spades', 'Hearts', 'Diamonds', 'Clubs']\n",
    "alias = suits\n",
    "suits = []\n",
    "print(suits, alias)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But using clear:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[] []\n"
     ]
    }
   ],
   "source": [
    "suits = ['Spades', 'Hearts', 'Diamonds', 'Clubs']\n",
    "alias = suits\n",
    "suits.clear()\n",
    "print(suits, alias)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Big difference!!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also replace elements using slicing and extended slicing. Here's an example, but we'll come back to this in a lot of detail:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932698504\n",
      "1979932698504 ['a', 'b', 'c', 'd', 'e', 3, 4, 5]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4, 5]\n",
    "print(id(l))\n",
    "l[0:2] = ['a', 'b', 'c', 'd', 'e']\n",
    "print(id(l), l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Appending and Extending"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also append elements to the sequence (note that this is **not** the same as concatenation):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932697992\n",
      "[1, 2, 3, 4] 1979932697992\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3]\n",
    "print(id(l))\n",
    "l.append(4)\n",
    "print(l, id(l))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we had \"appended\" the value `4` using concatenation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932193288\n",
      "1979932698312 [1, 2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3]\n",
    "print(id(l))\n",
    "l = l + [4]\n",
    "print(id(l), l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we want to add more than one element at a time, we can extend a sequence with the contents of any iterable (not just sequences):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932844488\n",
      "1979932844488 [1, 2, 3, 4, 5, 'c', 'b', 'a']\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4, 5]\n",
    "print(id(l))\n",
    "l.extend({'a', 'b', 'c'})\n",
    "print(id(l), l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course, since we extended using a set, there was not gurantee of positional ordering."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we extend with another sequence, then positional ordering is retained:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 'a', 'b', 'c']\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3]\n",
    "l.extend(('a', 'b', 'c'))\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Removing Elements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can remove (and retrieve at the same time) an element from a mutable sequence:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932193288\n",
      "1979932193288 2 [1, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4]\n",
    "print(id(l))\n",
    "popped = l.pop(1)\n",
    "print(id(l), popped, l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we do not specify an index for `pop`, then the **last** element is popped:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n",
      "1979932696968 4 [1, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4]\n",
    "popped = l.pop()\n",
    "print(popped)\n",
    "print(id(l), popped, l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Inserting Elements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can insert an element at a specific index. What this means is that the element we are inserting will be **at** that index position, and element that was at that position and all the remaining elements to the right are pushed out:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932143176\n",
      "1979932143176 [1, 'a', 2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4]\n",
    "print(id(l))\n",
    "l.insert(1, 'a')\n",
    "print(id(l), l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Reversing a Sequence"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also do in-place reversal:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979930587080\n",
      "1979930587080 [4, 3, 2, 1]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4]\n",
    "print(id(l))\n",
    "l.reverse()\n",
    "print(id(l), l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also reverse a sequence using extended slicing (we'll come back to this later):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4, 3, 2, 1]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l = [1, 2, 3, 4]\n",
    "l[::-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But this is **NOT** mutating the sequence - the slice is returning a **new** sequence - that happens to be reversed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932143176\n",
      "1979932696968 [4, 3, 2, 1]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4]\n",
    "print(id(l))\n",
    "l = l[::-1]\n",
    "print(id(l), l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Copying Sequences"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can create a copy of a sequence:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932700040\n",
      "1979932696968 [1, 2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4]\n",
    "print(id(l))\n",
    "l2 = l.copy()\n",
    "print(id(l2), l2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the `id` of `l` and `l2` is not the same."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this case, using slicing does work the same as using the `copy` method:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1979932847304\n",
      "1979932700040 [1, 2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3, 4]\n",
    "print(id(l))\n",
    "l2 = l[:]\n",
    "print(id(l2), l2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see in both cases we end up with new objects.\n",
    "\n",
    "So, use copy() or [:] - up to you, they end up doing the same thing."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll come back to copying in some detail in an upcoming video as this is an important topic with some subtleties."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
